home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Modules / rgbimgmodule.c < prev    next >
Text File  |  1995-12-21  |  16KB  |  753 lines

  1. /*
  2.  *       fastimg -
  3.  *        Faster reading and writing of image files.
  4.  *
  5.  *      This code should work on machines with any byte order.
  6.  *
  7.  *    Could someone make this run real fast using multiple processors 
  8.  *    or how about using memory mapped files to speed it up?
  9.  *
  10.  *                Paul Haeberli - 1991
  11.  *
  12.  *    Changed to return sizes.
  13.  *                Sjoerd Mullender - 1993
  14.  *    Changed to incorporate into Python.
  15.  *                Sjoerd Mullender - 1993
  16.  */
  17. #include "allobjects.h"
  18. #include "modsupport.h"
  19. #ifdef HAVE_UNISTD_H
  20. #include <unistd.h>
  21. #endif
  22. #include <string.h>
  23.  
  24. /*
  25.  *    from image.h
  26.  *
  27.  */
  28. typedef struct {
  29.     unsigned short    imagic;        /* stuff saved on disk . . */
  30.     unsigned short     type;
  31.     unsigned short     dim;
  32.     unsigned short     xsize;
  33.     unsigned short     ysize;
  34.     unsigned short     zsize;
  35.     unsigned long     min;
  36.     unsigned long     max;
  37.     unsigned long    wastebytes;    
  38.     char         name[80];
  39.     unsigned long    colormap;
  40.  
  41.     long         file;        /* stuff used in core only */
  42.     unsigned short     flags;
  43.     short        dorev;
  44.     short        x;
  45.     short        y;
  46.     short        z;
  47.     short        cnt;
  48.     unsigned short    *ptr;
  49.     unsigned short    *base;
  50.     unsigned short    *tmpbuf;
  51.     unsigned long    offset;
  52.     unsigned long    rleend;        /* for rle images */
  53.     unsigned long    *rowstart;    /* for rle images */
  54.     long        *rowsize;    /* for rle images */
  55. } IMAGE;
  56.  
  57. #define IMAGIC     0732
  58.  
  59. #define TYPEMASK        0xff00
  60. #define BPPMASK            0x00ff
  61. #define ITYPE_VERBATIM        0x0000
  62. #define ITYPE_RLE        0x0100
  63. #define ISRLE(type)        (((type) & 0xff00) == ITYPE_RLE)
  64. #define ISVERBATIM(type)    (((type) & 0xff00) == ITYPE_VERBATIM)
  65. #define BPP(type)        ((type) & BPPMASK)
  66. #define RLE(bpp)        (ITYPE_RLE | (bpp))
  67. #define VERBATIM(bpp)        (ITYPE_VERBATIM | (bpp))
  68. /*
  69.  *    end of image.h stuff
  70.  *
  71.  */
  72.  
  73. #define RINTLUM (79)
  74. #define GINTLUM (156)
  75. #define BINTLUM (21)
  76.  
  77. #define ILUM(r,g,b)     ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8)
  78.  
  79. #define OFFSET_R    3    /* this is byte order dependent */
  80. #define OFFSET_G    2
  81. #define OFFSET_B    1
  82. #define OFFSET_A    0
  83.  
  84. #define CHANOFFSET(z)    (3-(z))    /* this is byte order dependent */
  85.  
  86. static expandrow PROTO((unsigned char *, unsigned char *, int));
  87. static setalpha PROTO((unsigned char *, int));
  88. static copybw PROTO((long *, int));
  89. static interleaverow PROTO((unsigned char *, unsigned char *, int, int));
  90. static int compressrow PROTO((unsigned char *, unsigned char *, int, int));
  91. static lumrow PROTO((unsigned char *, unsigned char *, int));
  92.  
  93. #ifdef ADD_TAGS
  94. #define TAGLEN    (5)
  95. #else
  96. #define TAGLEN    (0)
  97. #endif
  98.  
  99. static object *ImgfileError;
  100.  
  101. static int reverse_order;
  102.  
  103. #ifdef ADD_TAGS
  104. /*
  105.  *    addlongimgtag - 
  106.  *        this is used to extract image data from core dumps.
  107.  *
  108.  */
  109. addlongimgtag(dptr,xsize,ysize)
  110. unsigned long *dptr;
  111. int xsize, ysize;
  112. {
  113.     dptr = dptr+(xsize*ysize);
  114.     dptr[0] = 0x12345678;
  115.     dptr[1] = 0x59493333;
  116.     dptr[2] = 0x69434222;
  117.     dptr[3] = xsize;
  118.     dptr[4] = ysize;
  119. }
  120. #endif
  121.  
  122. /*
  123.  *    byte order independent read/write of shorts and longs.
  124.  *
  125.  */
  126. static unsigned short getshort(inf)
  127. FILE *inf;
  128. {
  129.     unsigned char buf[2];
  130.  
  131.     fread(buf,2,1,inf);
  132.     return (buf[0]<<8)+(buf[1]<<0);
  133. }
  134.  
  135. static unsigned long getlong(inf)
  136. FILE *inf;
  137. {
  138.     unsigned char buf[4];
  139.  
  140.     fread(buf,4,1,inf);
  141.     return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0);
  142. }
  143.  
  144. static putshort(outf,val)
  145. FILE *outf;
  146. unsigned short val;
  147. {
  148.     unsigned char buf[2];
  149.  
  150.     buf[0] = (val>>8);
  151.     buf[1] = (val>>0);
  152.     fwrite(buf,2,1,outf);
  153. }
  154.  
  155. static int putlong(outf,val)
  156. FILE *outf;
  157. unsigned long val;
  158. {
  159.     unsigned char buf[4];
  160.  
  161.     buf[0] = (val>>24);
  162.     buf[1] = (val>>16);
  163.     buf[2] = (val>>8);
  164.     buf[3] = (val>>0);
  165.     return fwrite(buf,4,1,outf);
  166. }
  167.  
  168. static readheader(inf,image)
  169. FILE *inf;
  170. IMAGE *image;
  171. {
  172.     memset(image,0,sizeof(IMAGE));
  173.     image->imagic = getshort(inf);
  174.     image->type = getshort(inf);
  175.     image->dim = getshort(inf);
  176.     image->xsize = getshort(inf);
  177.     image->ysize = getshort(inf);
  178.     image->zsize = getshort(inf);
  179. }
  180.  
  181. static int writeheader(outf,image)
  182. FILE *outf;
  183. IMAGE *image;
  184. {
  185.     IMAGE t;
  186.  
  187.     memset(&t,0,sizeof(IMAGE));
  188.     fwrite(&t,sizeof(IMAGE),1,outf);
  189.     fseek(outf,0,SEEK_SET);
  190.     putshort(outf,image->imagic);
  191.     putshort(outf,image->type);
  192.     putshort(outf,image->dim);
  193.     putshort(outf,image->xsize);
  194.     putshort(outf,image->ysize);
  195.     putshort(outf,image->zsize);
  196.     putlong(outf,image->min);
  197.     putlong(outf,image->max);
  198.     putlong(outf,0);
  199.     return fwrite("no name",8,1,outf);
  200. }
  201.  
  202. static int writetab(outf,tab,len)
  203. FILE *outf;
  204. /*unsigned*/ long *tab;
  205. int len;
  206. {
  207.     int r;
  208.  
  209.     while(len) {
  210.     r = putlong(outf,*tab++);
  211.     len -= 4;
  212.     }
  213.     return r;
  214. }
  215.  
  216. static readtab(inf,tab,len)
  217. FILE *inf;
  218. /*unsigned*/ long *tab;
  219. int len;
  220. {
  221.     while(len) {
  222.     *tab++ = getlong(inf);
  223.     len -= 4;
  224.     }
  225. }
  226.  
  227. /*
  228.  *    sizeofimage - 
  229.  *        return the xsize and ysize of an iris image file.
  230.  *
  231.  */
  232. static object *
  233. sizeofimage(self, args)
  234.     object *self, *args;
  235. {
  236.     char *name;
  237.     IMAGE image;
  238.     FILE *inf;
  239.  
  240.     if (!getargs(args, "s", &name))
  241.     return NULL;
  242.  
  243.     inf = fopen(name,"r");
  244.     if(!inf) {
  245.     err_setstr(ImgfileError, "can't open image file");
  246.     return NULL;
  247.     }
  248.     readheader(inf,&image);
  249.     fclose(inf);
  250.     if(image.imagic != IMAGIC) {
  251.     err_setstr(ImgfileError, "bad magic number in image file");
  252.     return NULL;
  253.     }
  254.     return mkvalue("(ii)", image.xsize, image.ysize);
  255. }
  256.  
  257. /*
  258.  *    longimagedata - 
  259.  *        read in a B/W RGB or RGBA iris image file and return a 
  260.  *    pointer to an array of longs.
  261.  *
  262.  */
  263. static object *
  264. longimagedata(self, args)
  265.     object *self, *args;
  266. {
  267.     char *name;
  268.     unsigned char *base, *lptr;
  269.     unsigned char *rledat, *verdat;
  270.     long *starttab, *lengthtab;
  271.     FILE *inf;
  272.     IMAGE image;
  273.     int y, z, tablen;
  274.     int xsize, ysize, zsize;
  275.     int bpp, rle, cur, badorder;
  276.     int rlebuflen;
  277.     object *rv;
  278.  
  279.     if (!getargs(args, "s", &name))
  280.     return NULL;
  281.  
  282.     inf = fopen(name,"r");
  283.     if(!inf) {
  284.     err_setstr(ImgfileError,"can't open image file");
  285.     return NULL;
  286.     }
  287.     readheader(inf,&image);
  288.     if(image.imagic != IMAGIC) {
  289.     err_setstr(ImgfileError,"bad magic number in image file");
  290.     fclose(inf);
  291.     return NULL;
  292.     }
  293.     rle = ISRLE(image.type);
  294.     bpp = BPP(image.type);
  295.     if(bpp != 1 ) {
  296.     err_setstr(ImgfileError,"image must have 1 byte per pix chan");
  297.     fclose(inf);
  298.     return NULL;
  299.     }
  300.     xsize = image.xsize;
  301.     ysize = image.ysize;
  302.     zsize = image.zsize;
  303.     if(rle) {
  304.     tablen = ysize*zsize*sizeof(long);
  305.     starttab = (long *)malloc(tablen);
  306.     lengthtab = (long *)malloc(tablen);
  307.     rlebuflen = 1.05*xsize+10;
  308.     rledat = (unsigned char *)malloc(rlebuflen);
  309.     fseek(inf,512,SEEK_SET);
  310.      readtab(inf,starttab,tablen);
  311.     readtab(inf,lengthtab,tablen);
  312.  
  313. /* check data order */
  314.     cur = 0;
  315.     badorder = 0;
  316.     for(y=0; y<ysize; y++) {
  317.         for(z=0; z<zsize; z++) {
  318.         if(starttab[y+z*ysize]<cur) {
  319.             badorder = 1;
  320.             break;
  321.         }
  322.         cur = starttab[y+z*ysize];
  323.         }
  324.         if(badorder) 
  325.         break;
  326.     }
  327.  
  328.     fseek(inf,512+2*tablen,SEEK_SET);
  329.     cur = 512+2*tablen;
  330.     rv = newsizedstringobject((char *) 0,
  331.                   (xsize*ysize+TAGLEN)*sizeof(long));
  332.     if (rv == NULL) {
  333.         fclose(inf);
  334.         free(lengthtab);
  335.         free(starttab);
  336.         free(rledat);
  337.         return NULL;
  338.     }
  339.     base = (unsigned char *) getstringvalue(rv);
  340. #ifdef ADD_TAGS
  341.     addlongimgtag(base,xsize,ysize);
  342. #endif
  343.       if(badorder) {
  344.         for(z=0; z<zsize; z++) {
  345.         lptr = base;
  346.         if (reverse_order)
  347.             lptr += (ysize - 1) * xsize * sizeof(unsigned long);
  348.         for(y=0; y<ysize; y++) {
  349.             if(cur != starttab[y+z*ysize]) {
  350.             fseek(inf,starttab[y+z*ysize],SEEK_SET);
  351.             cur = starttab[y+z*ysize];
  352.             }
  353.             if(lengthtab[y+z*ysize]>rlebuflen) {
  354.             err_setstr(ImgfileError,"rlebuf is too small - bad poop");
  355.             fclose(inf);
  356.             DECREF(rv);
  357.             free(rledat);
  358.             free(starttab);
  359.             free(lengthtab);
  360.             return NULL;
  361.             }
  362.             fread(rledat,lengthtab[y+z*ysize],1,inf);
  363.             cur += lengthtab[y+z*ysize];
  364.             expandrow(lptr,rledat,3-z);
  365.             if (reverse_order)
  366.             lptr -= xsize * sizeof(unsigned long);
  367.             else
  368.             lptr += xsize * sizeof(unsigned long);
  369.         }
  370.         }
  371.     } else {
  372.         lptr = base;
  373.         if (reverse_order)
  374.         lptr += (ysize - 1) * xsize * sizeof(unsigned long);
  375.         for(y=0; y<ysize; y++) {
  376.         for(z=0; z<zsize; z++) {
  377.             if(cur != starttab[y+z*ysize]) {
  378.             fseek(inf,starttab[y+z*ysize],SEEK_SET);
  379.             cur = starttab[y+z*ysize];
  380.             }
  381.             fread(rledat,lengthtab[y+z*ysize],1,inf);
  382.             cur += lengthtab[y+z*ysize];
  383.             expandrow(lptr,rledat,3-z);
  384.         }
  385.         if (reverse_order)
  386.             lptr -= xsize * sizeof(unsigned long);
  387.         else
  388.             lptr += xsize * sizeof(unsigned long);
  389.         }
  390.         }
  391.     if(zsize == 3) 
  392.         setalpha(base,xsize*ysize);
  393.     else if(zsize<3) 
  394.         copybw((long *) base,xsize*ysize);
  395.     fclose(inf);
  396.     free(starttab);
  397.     free(lengthtab);
  398.     free(rledat);
  399.     return rv;
  400.     } else {
  401.     rv = newsizedstringobject((char *) 0,
  402.                   (xsize*ysize+TAGLEN)*sizeof(long));
  403.     if (rv == NULL) {
  404.         fclose(inf);
  405.         return NULL;
  406.     }
  407.     base = (unsigned char *) getstringvalue(rv);
  408. #ifdef ADD_TAGS
  409.     addlongimgtag(base,xsize,ysize);
  410. #endif
  411.     verdat = (unsigned char *)malloc(xsize);
  412.     fseek(inf,512,SEEK_SET);
  413.     for(z=0; z<zsize; z++) {
  414.         lptr = base;
  415.         if (reverse_order)
  416.         lptr += (ysize - 1) * xsize * sizeof(unsigned long);
  417.         for(y=0; y<ysize; y++) {
  418.         fread(verdat,xsize,1,inf);
  419.         interleaverow(lptr,verdat,3-z,xsize);
  420.         if (reverse_order)
  421.             lptr -= xsize * sizeof(unsigned long);
  422.         else
  423.             lptr += xsize * sizeof(unsigned long);
  424.         }
  425.     }
  426.     if(zsize == 3) 
  427.         setalpha(base,xsize*ysize);
  428.     else if(zsize<3) 
  429.         copybw((long *) base,xsize*ysize);
  430.     fclose(inf);
  431.     free(verdat);
  432.     return rv;
  433.     }
  434. }
  435.  
  436. /* static utility functions for longimagedata */
  437.  
  438. static interleaverow(lptr,cptr,z,n)
  439. unsigned char *lptr, *cptr;
  440. int z, n;
  441. {
  442.     lptr += z;
  443.     while(n--) {
  444.     *lptr = *cptr++;
  445.     lptr += 4;
  446.     }
  447. }
  448.  
  449. static copybw(lptr,n)
  450. long *lptr;
  451. int n;
  452. {
  453.     while(n>=8) {
  454.     lptr[0] = 0xff000000+(0x010101*(lptr[0]&0xff));
  455.     lptr[1] = 0xff000000+(0x010101*(lptr[1]&0xff));
  456.     lptr[2] = 0xff000000+(0x010101*(lptr[2]&0xff));
  457.     lptr[3] = 0xff000000+(0x010101*(lptr[3]&0xff));
  458.     lptr[4] = 0xff000000+(0x010101*(lptr[4]&0xff));
  459.     lptr[5] = 0xff000000+(0x010101*(lptr[5]&0xff));
  460.     lptr[6] = 0xff000000+(0x010101*(lptr[6]&0xff));
  461.     lptr[7] = 0xff000000+(0x010101*(lptr[7]&0xff));
  462.     lptr += 8;
  463.     n-=8;
  464.     }
  465.     while(n--) {
  466.     *lptr = 0xff000000+(0x010101*(*lptr&0xff));
  467.     lptr++;
  468.     }
  469. }
  470.  
  471. static setalpha(lptr,n)
  472. unsigned char *lptr;
  473. {
  474.     while(n>=8) {
  475.     lptr[0*4] = 0xff;
  476.     lptr[1*4] = 0xff;
  477.     lptr[2*4] = 0xff;
  478.     lptr[3*4] = 0xff;
  479.     lptr[4*4] = 0xff;
  480.     lptr[5*4] = 0xff;
  481.     lptr[6*4] = 0xff;
  482.     lptr[7*4] = 0xff;
  483.     lptr += 4*8;
  484.     n -= 8;
  485.     }
  486.     while(n--) {
  487.     *lptr = 0xff;
  488.     lptr += 4;
  489.     }
  490. }
  491.  
  492. static expandrow(optr,iptr,z)
  493. unsigned char *optr, *iptr;
  494. int z;
  495. {
  496.     unsigned char pixel, count;
  497.  
  498.     optr += z;
  499.     while(1) {
  500.     pixel = *iptr++;
  501.     if ( !(count = (pixel & 0x7f)) )
  502.         return;
  503.     if(pixel & 0x80) {
  504.         while(count>=8) {
  505.         optr[0*4] = iptr[0];
  506.         optr[1*4] = iptr[1];
  507.         optr[2*4] = iptr[2];
  508.         optr[3*4] = iptr[3];
  509.         optr[4*4] = iptr[4];
  510.         optr[5*4] = iptr[5];
  511.         optr[6*4] = iptr[6];
  512.         optr[7*4] = iptr[7];
  513.         optr += 8*4;
  514.         iptr += 8;
  515.         count -= 8;
  516.         }
  517.         while(count--) {
  518.         *optr = *iptr++;
  519.         optr+=4;
  520.         }
  521.     } else {
  522.         pixel = *iptr++;
  523.         while(count>=8) {
  524.         optr[0*4] = pixel;
  525.         optr[1*4] = pixel;
  526.         optr[2*4] = pixel;
  527.         optr[3*4] = pixel;
  528.         optr[4*4] = pixel;
  529.         optr[5*4] = pixel;
  530.         optr[6*4] = pixel;
  531.         optr[7*4] = pixel;
  532.         optr += 8*4;
  533.         count -= 8;
  534.         }
  535.         while(count--) {
  536.         *optr = pixel;
  537.         optr+=4;
  538.         }
  539.     }
  540.     }
  541. }
  542.  
  543. /*
  544.  *    longstoimage -
  545.  *        copy an array of longs to an iris image file.  Each long
  546.  *    represents one pixel.  xsize and ysize specify the dimensions of
  547.  *    the pixel array.  zsize specifies what kind of image file to
  548.  *    write out.  if zsize is 1, the luminance of the pixels are
  549.  *    calculated, and a sinlge channel black and white image is saved.
  550.  *    If zsize is 3, an RGB image file is saved.  If zsize is 4, an
  551.  *    RGBA image file is saved.
  552.  *
  553.  */
  554. static object *
  555. longstoimage(self, args)
  556.     object *self, *args;
  557. {
  558.     unsigned char *lptr;
  559.     char *name;
  560.     int xsize, ysize, zsize;
  561.     FILE *outf;
  562.     IMAGE image;
  563.     int tablen, y, z, pos, len;
  564.     long *starttab, *lengthtab;
  565.     unsigned char *rlebuf;
  566.     unsigned char *lumbuf;
  567.     int rlebuflen, goodwrite;
  568.  
  569.     if (!getargs(args, "(s#iiis)", &lptr, &len, &xsize, &ysize, &zsize, &name))
  570.     return NULL;
  571.  
  572.     goodwrite = 1;
  573.     outf = fopen(name,"w");
  574.     if(!outf) {
  575.     err_setstr(ImgfileError,"can't open output file");
  576.     return NULL;
  577.     }
  578.     tablen = ysize*zsize*sizeof(long);
  579.  
  580.     starttab = (long *)malloc(tablen);
  581.     lengthtab = (long *)malloc(tablen);
  582.     rlebuflen = 1.05*xsize+10;
  583.     rlebuf = (unsigned char *)malloc(rlebuflen);
  584.     lumbuf = (unsigned char *)malloc(xsize*sizeof(long));
  585.  
  586.     memset(&image,0,sizeof(IMAGE));
  587.     image.imagic = IMAGIC; 
  588.     image.type = RLE(1);
  589.     if(zsize>1)
  590.     image.dim = 3;
  591.     else
  592.     image.dim = 2;
  593.     image.xsize = xsize;
  594.     image.ysize = ysize;
  595.     image.zsize = zsize;
  596.     image.min = 0;
  597.     image.max = 255;
  598.     goodwrite *= writeheader(outf,&image);
  599.     fseek(outf,512+2*tablen,SEEK_SET);
  600.     pos = 512+2*tablen;
  601.     if (reverse_order)
  602.     lptr += (ysize - 1) * xsize * sizeof(unsigned long);
  603.     for(y=0; y<ysize; y++) {
  604.     for(z=0; z<zsize; z++) {
  605.         if(zsize == 1) {
  606.         lumrow(lptr,lumbuf,xsize);
  607.         len = compressrow(lumbuf,rlebuf,CHANOFFSET(z),xsize);
  608.         } else {
  609.         len = compressrow(lptr,rlebuf,CHANOFFSET(z),xsize);
  610.         }
  611.         if(len>rlebuflen) {
  612.         err_setstr(ImgfileError,"rlebuf is too small - bad poop");
  613.         free(starttab);
  614.         free(lengthtab);
  615.         free(rlebuf);
  616.         free(lumbuf);
  617.         fclose(outf);
  618.         return NULL;
  619.         }
  620.         goodwrite *= fwrite(rlebuf,len,1,outf);
  621.         starttab[y+z*ysize] = pos;
  622.         lengthtab[y+z*ysize] = len;
  623.         pos += len;
  624.     }
  625.     if (reverse_order)
  626.         lptr -= xsize * sizeof(unsigned long);
  627.     else
  628.         lptr += xsize * sizeof(unsigned long);
  629.     }
  630.  
  631.     fseek(outf,512,SEEK_SET);
  632.     goodwrite *= writetab(outf,starttab,tablen);
  633.     goodwrite *= writetab(outf,lengthtab,tablen);
  634.     free(starttab);
  635.     free(lengthtab);
  636.     free(rlebuf);
  637.     free(lumbuf);
  638.     fclose(outf);
  639.     if(goodwrite) {
  640.     INCREF(None);
  641.     return None;
  642.     } else {
  643.     err_setstr(ImgfileError,"not enough space for image!!");
  644.     return NULL;
  645.     }
  646. }
  647.  
  648. /* static utility functions for longstoimage */
  649.  
  650. static lumrow(rgbptr,lumptr,n) 
  651. unsigned char *rgbptr, *lumptr;
  652. int n;
  653. {
  654.     lumptr += CHANOFFSET(0);
  655.     while(n--) {
  656.     *lumptr = ILUM(rgbptr[OFFSET_R],rgbptr[OFFSET_G],rgbptr[OFFSET_B]);
  657.     lumptr += 4;
  658.     rgbptr += 4;
  659.     }
  660. }
  661.  
  662. static int compressrow(lbuf,rlebuf,z,cnt)
  663. unsigned char *lbuf, *rlebuf;
  664. int z, cnt;
  665. {
  666.     unsigned char *iptr, *ibufend, *sptr, *optr;
  667.     short todo, cc;                            
  668.     long count;
  669.  
  670.     lbuf += z;
  671.     iptr = lbuf;
  672.     ibufend = iptr+cnt*4;
  673.     optr = rlebuf;
  674.  
  675.     while(iptr<ibufend) {
  676.     sptr = iptr;
  677.     iptr += 8;
  678.     while((iptr<ibufend)&& ((iptr[-8]!=iptr[-4])||(iptr[-4]!=iptr[0])))
  679.         iptr+=4;
  680.     iptr -= 8;
  681.     count = (iptr-sptr)/4;
  682.     while(count) {
  683.         todo = count>126 ? 126:count;
  684.         count -= todo;
  685.         *optr++ = 0x80|todo;
  686.         while(todo>8) {
  687.         optr[0] = sptr[0*4];
  688.         optr[1] = sptr[1*4];
  689.         optr[2] = sptr[2*4];
  690.         optr[3] = sptr[3*4];
  691.         optr[4] = sptr[4*4];
  692.         optr[5] = sptr[5*4];
  693.         optr[6] = sptr[6*4];
  694.         optr[7] = sptr[7*4];
  695.         optr += 8;
  696.         sptr += 8*4;
  697.         todo -= 8;
  698.         }
  699.         while(todo--) {
  700.         *optr++ = *sptr;
  701.         sptr += 4;
  702.         }
  703.     }
  704.     sptr = iptr;
  705.     cc = *iptr;
  706.     iptr += 4;
  707.     while( (iptr<ibufend) && (*iptr == cc) )
  708.         iptr += 4;
  709.     count = (iptr-sptr)/4;
  710.     while(count) {
  711.         todo = count>126 ? 126:count;
  712.         count -= todo;
  713.         *optr++ = todo;
  714.         *optr++ = cc;
  715.     }
  716.     }
  717.     *optr++ = 0;
  718.     return optr - (unsigned char *)rlebuf;
  719. }
  720.  
  721. static object *
  722. ttob(self, args)
  723.     object *self;
  724.     object *args;
  725. {
  726.     int order, oldorder;
  727.  
  728.     if (!getargs(args, "i", &order))
  729.     return NULL;
  730.     oldorder = reverse_order;
  731.     reverse_order = order;
  732.     return newintobject(oldorder);
  733. }
  734.  
  735. static struct methodlist rgbimg_methods[] = {
  736.     {"sizeofimage",    sizeofimage},
  737.     {"longimagedata",    longimagedata},
  738.     {"longstoimage",    longstoimage},
  739.     {"ttob",        ttob},
  740.     {NULL, NULL}        /* sentinel */
  741. };
  742.  
  743. void
  744. initrgbimg()
  745. {
  746.     object *m, *d;
  747.     m = initmodule("rgbimg", rgbimg_methods);
  748.     d = getmoduledict(m);
  749.     ImgfileError = newstringobject("rgbimg.error");
  750.     if (ImgfileError == NULL || dictinsert(d, "error", ImgfileError))
  751.     fatal("can't define rgbimg.error");
  752. }
  753.